package cn.gcjxsc.payment.messaging.sink;

import cn.gcjxsc.common.consts.PayStatus;
import cn.gcjxsc.common.data.notify.redpack.RedPackData;
import cn.gcjxsc.common.data.notify.redpack.RedPackResultData;
import cn.gcjxsc.common.data.wx.redpack.SendResponse;
import cn.gcjxsc.common.util.validator.BindResult;
import cn.gcjxsc.payment.data.RedPackConfig;
import cn.gcjxsc.payment.data.WeChatConfig;
import cn.gcjxsc.payment.data.wx.redpack.SendData;
import cn.gcjxsc.payment.entity.wx.RedPackRecord;
import cn.gcjxsc.payment.messaging.source.RedPackResultSource;
import cn.gcjxsc.payment.service.wx.RedPackService;
import com.zgxl.common.util.XmlUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.stream.annotation.EnableBinding;
import org.springframework.cloud.stream.annotation.Input;
import org.springframework.cloud.stream.annotation.StreamListener;
import org.springframework.messaging.SubscribableChannel;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;

/**
 * 发送红包订阅通知.
 *
 * @author pumbaa
 * @since 1.0
 */
@EnableBinding(RedPackSink.Sink.class)
public class RedPackSink {
    private Logger logger = LoggerFactory.getLogger(RedPackSink.class);
    @Value("${spring.profiles.active}")
    private String active;
    @Autowired
    private RedPackService redPackService;
    @Autowired
    private WeChatConfig weChatConfig;
    @Autowired
    private RedPackConfig redPackConfig;
    @Autowired
    private RedPackResultSource source;

    private static final String SUCCESS = "00";
    private static final String FAIL = "01";

    /**
     * 处理红包通知.
     *
     * @param data
     */
    @StreamListener(Sink.QUEUE_NAME)
    public void process(RedPackData data) {
        BindResult bindResult  = new BindResult();
        //检查数据
        if (!redPackService.checkInputData(data, bindResult)) {
            logger.error("提交红包发送失败.{}", bindResult.getErrorMsg());
            return;
        }
        RedPackRecord redPackRecord = redPackService.findBySnAndType(data.getSn(), data.getType());
        if (null == redPackRecord) {
            redPackRecord = new RedPackRecord();
            redPackRecord.setAmount(data.getAmount());
            redPackRecord.setCreated(System.currentTimeMillis()/1000);
            redPackRecord.setOpenid(data.getOpenid());
            redPackRecord.setSn(data.getSn());
            redPackRecord.setRemark(data.getRemark());
            redPackRecord.setStatus(PayStatus.UNPAY.ordinal());
            redPackRecord.setStoreId(data.getStoreId());
            redPackRecord.setType(data.getType());
            redPackRecord.setOutTradeNo("");
            redPackRecord.setTradeNo(redPackService.createTradeNo("hb"));
            redPackRecord.setStoreName(data.getStoreName());
            redPackRecord.setDoneTime(0L);
            try {
                redPackRecord = redPackService.saveRedPackRecord(redPackRecord);
            } catch (Exception e) {
                sendResult(redPackRecord, FAIL);
                logger.error("保存红包记录失败.订单号:{},类型:{},错误:{}", data.getSn(), e.getMessage());
                return;
            }
        }
        else {
            if (redPackRecord.getStatus() == PayStatus.PAID.ordinal()) {
                logger.info("当前数据已成功发送红包.{}, {}", data.getSn(), data.getType());
                return;
            }
        }
        SendData sendData = redPackService.prepareSendData(redPackRecord, redPackConfig);


        SendResponse sendResponse;
        //发送红包
        if (active.equals("prod")) {
            HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
            sendData.setClientIp(request.getRemoteHost());
            sendResponse = redPackService.sendRedPack(weChatConfig, sendData, bindResult);
        }
        else {
            sendData.setClientIp(getIpAddress());
            String xml = "<xml>\n" +
                    "    <return_code><![CDATA[SUCCESS]]></return_code>\n" +
                    "    <return_msg><![CDATA[发放成功]]></return_msg>\n" +
                    "    <result_code><![CDATA[SUCCESS]]></result_code>\n" +
                    "    <err_code><![CDATA[SUCCESS]]></err_code>\n" +
                    "    <err_code_des><![CDATA[发放成功]]></err_code_des>\n" +
                    "    <mch_billno><![CDATA[1510302457734]]></mch_billno>\n" +
                    "    <mch_id><![CDATA[1396594402]]></mch_id>\n" +
                    "    <wxappid><![CDATA[wx2a26d71ce7a2742b]]></wxappid>\n" +
                    "    <re_openid><![CDATA[oHr5cxL4yDuqLDPI0vqNRQ0f6-p4]]></re_openid>\n" +
                    "    <total_amount>100</total_amount>\n" +
                    "    <send_listid><![CDATA[1000041701201711103000133856138]]></send_listid>\n" +
                    "</xml>";
            sendResponse = XmlUtil.convertToObject(SendResponse.class, xml);
        }
        if (null == sendResponse) {
            logger.error("请求发送红包失败.{}, {}, {}", data.getSn(), data.getType(), bindResult.getErrorMsg());
            sendResult(redPackRecord, FAIL);
            return;
        }
        if (redPackService.isRedPackSendSuccess(sendResponse)) {
            logger.info("红包发送成功.{}, {}", data.getSn(), data.getType());

            redPackRecord.setStatus(PayStatus.PAID.ordinal());
            redPackRecord.setOutTradeNo(sendResponse.getSend_listid());
            redPackRecord.setDoneTime(System.currentTimeMillis()/1000);
            try {
                redPackService.updateRedPackRecord(redPackRecord);
            } catch (Exception e) {
                sendResult(redPackRecord, FAIL);
                logger.error("红包发送成功,更新记录失败.{}, {}, {}", data.getSn(), data.getType(), e.getMessage());
                return;
            }
            sendResult(redPackRecord, SUCCESS);
        }
        else {
            logger.error("请求发送红包结果失败:{}, {}, {}, {}", data.getSn(), data.getType(), sendResponse.getReturn_msg(), sendResponse.getErr_code_des());
            sendResult(redPackRecord, FAIL);
        }
    }

    private void sendResult(RedPackRecord record, String status){
        RedPackResultData data = new RedPackResultData();
        data.setAmount(record.getAmount());
        data.setOpenid(record.getOpenid());
        data.setOutTradeNo(record.getOutTradeNo());
        data.setSn(record.getSn());
        data.setStatus(status);
        data.setType(record.getType());
        data.setTradeNo(record.getTradeNo());

        source.sendRedPackResultMessage(data);
    }

    private String getIpAddress(){
        return "183.230.163.94";
    }

    public interface Sink {
        String QUEUE_NAME = "rw_wx_redpack_input";

        @Input(QUEUE_NAME)
        SubscribableChannel input();
    }
}
